package org.chaiyi.template.core.register.contractor.proxy;

import org.chaiyi.template.core.common.exception.BaseErrorCode;
import org.chaiyi.template.core.common.repository.MongoEntity;
import org.chaiyi.template.core.common.repository.QueryInfo;
import org.chaiyi.template.core.common.util.asserts.Asserts;
import org.chaiyi.template.core.framework.mongo.Repository;

import java.lang.reflect.Method;
import java.util.Map;

/**
 * Contractor方法管理者
 *
 * @author Gong.Yang
 */
public class ContractorMethodManager {
    private static Map<String, ContractorMethod> methodMap = Map.of(
            "query_QueryInfo", (repository, args) -> {
                QueryInfo queryInfo = (QueryInfo) args[2];
                return repository.findList((String) args[0], (String) args[1], queryInfo.pageQuery());
            },
            "count_QueryInfo", (repository, args) -> {
                QueryInfo queryInfo = (QueryInfo) args[2];
                return repository.count((String) args[0], (String) args[1], queryInfo.pageQuery());
            },
            "create_entity", (repository, args) -> {
                return repository.create((String) args[0], (String) args[1], (MongoEntity) args[2]);
            },
            "getById_String",(repository, args) -> repository.findItem((String) args[0], (String) args[1], (String) args[2]),
            "modify_entity",(repository, args) -> {
                MongoEntity arg = (MongoEntity) args[2];
                BaseErrorCode.KEY_NOT_FIND_EXCEPTION.throwIf(Asserts.isBlank(arg.getId()));
                return repository.findItem((String) args[0], (String) args[1], arg.getId())
                        .flatMap(x-> repository.save((String) args[0], (String) args[1], arg));
            },
            "delete_String",(repository, args) -> repository.deleteById((String) args[0], (String) args[1], (String) args[2]));


    public static String isContractorMethod(Class<?> entityClass, Method method, Object[] args) {
        String key = buildKey(entityClass, method, args);
        return methodMap.containsKey(key) ? key : null;
    }

    public static Object intercept(String key, Repository repository, Object[] args) {
        return methodMap.get(key).intercept(repository, args);
    }

    private static String buildKey(Class<?> entityClass, Method method, Object[] args) {
        if (args.length != 3 || null == args[2]) return "null";
        Object arg3 = args[2];

        return method.getName() + "_" +
                (Asserts.eq(arg3.getClass(), entityClass) ?
                        "entity" : arg3.getClass().getSimpleName());
    }

    private static interface ContractorMethod {
        Object intercept(Repository repository, Object[] args);
    }
}
